/* 
 **************************************************************************
	 _____   _____   _   _   
	| ____| |  _  \ | | / /  
	| |__   | | | | | |/ /   
	|  __|  | | | | | |\ \   
	| |___  | |_| | | | \ \  
	|_____| |_____/ |_|  \_\ 
 
	Version: 	0.1.1
	Author: 	Frank Cheung
	QQ: 		799887651
	Email: 		frank@ajaxjs.com
	Web: 		www.ajaxjs.com
	Licenses: 	Berkeley Software Distribution，BSD
	本代码可以免费使用、修改，希望我的程序能为您的工作带来方便，同时请保留以上请息。

	BEGIN LICENSE BLOCK
	
	Copyright 版权所有 (c) 2011 Frank Cheung

	任何获得本软件副本及相关文档文件（下面简称为“软件”）的个人都可以免费获得不受限制处置本软件的权限，
	包括不受限制地使用、复制、修改、合并、出版、分发、重新许可或者销售本软件的副本，
	并且在满足下述条件时，允许本软件的受让人获得下述权限：

	在本软件的所有或者重要部分中包含上述版权公告信息和本权限公告信息。

	本软件不提供保证，不包含任何类型的保证（无论是明指的还是暗喻的），
	包含但不限于关于本软件的适销性、特定用途的适用性和无侵权保证。
	在任何情况下，无论是否签订了合约、存在侵权行为还是在其他情况下，
	本软件作者或版权持有人不对由本软件直接或间接产生的
	或由使用本软件或处置本软件所产生的任何索赔、损坏或者其他责任。
	
	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:
	
	The above copyright notice and this permission notice shall be included in
	all copies or substantial portions of the Software.
	
	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	THE SOFTWARE.
	
	END LICENSE BLOCK

 ***************************************************************************/

//*************************************************************************
// Edk.js它具备very core的特性。
// 此外，它既可以在客户端运行，也可以满足服务端DSL的要求，一物两用。
//*************************************************************************

/* $$表示Edk，何解？没什么，只是因为Edk不如敲打“$$”来得轻松：） */
if(!this['$$'])  $$ = {}; // init Namespace

/**
 * Douglas Crockford 基于原型的基础方法。
 * Ref. http://javascript.crockford.com/prototypal.html
 * newObject = Object.create(oldObject);
 * 2008-04-07
 * @param {Object} ource 原型对象
 */
Object.create = function(source){
	var dummy = source.constructor != Object ? source.constructor : function (){};
	dummy.prototype	= source;
	
	return new dummy(arguments[1], arguments[2], arguments[3], arguments[4]);
}

/**
 * 继承。
 * @param {Object} target	子类
 * @param {Object} source	父类
 */
Object.inherit = function(target, source){
	 // 定义继承阶段不要执行构造函数，所以不好使用Object.create() 
	function dummy(){}
	dummy.prototype	= source;

	var clone = new dummy;
	
	for(var i in target){
		clone[i] = target[i];
	}
	if(target.constructor != Object){
		clone.constructor = target.constructor; // patch for JSCript
	}
	return clone;
}

/**
 * 多继承。
 */
Object.mix = function(){
	var 
	 baseObj	= arguments[0]
	,target 
	,targets	= Array.prototype.slice.call(arguments, 1)
	,superObj;
	
	/**
	 * 继承。
	 * @param	{Object}	target				子类
	 * @param	{Object}	source				父类
	 */
	function inheritWITHOUTconstructor(target, source){
		 // 定义继承阶段不要执行构造函数，所以不好使用Object.create() 
		function dummy(){}
		dummy.prototype	= source;
	
		var clone = new dummy;
		
		for(var i in target){
			clone[i] = target[i];
		}

		return clone;
	}

	for(var i = 0, j = targets.length, superObj = baseObj; i < j; i++){
		target		= targets[i];
		if(!target)throw '不存在某个类！';
		superObj	= inheritWITHOUTconstructor(target, superObj);
	}
	
	return superObj;
}

/**
 * 将一个数组插入另外一个数组的指定位置
 * @param {Array}  target
 * @param {Number} insertIndex 
 * @param {Array}  arr
 * @return {Array}
 */
Array.insert = function(target, insertIndex, arr){
	return target.splice.apply(target, Array.concat.call(insertIndex, 0, arr));
}

Array.indexOf = function(arr, el){
	for(var i = 0, j = arr.length; i < j; i++){
		if(arr[i] == el){
			return i;
		}
	}
	return -1;
}

Array.remove = function(arr, el){
	var index = Array.indexOf(arr, el);
	arr.splice(index, 1);
	return el;
}

/**
 * 格式化字符串。字符串格式型如：“foo{0}bar{1}……”。
 * @param	{String []}  可变长度的字符串参数。
 * @this 	{String}
 * @return 	{String}
 */
String.prototype.format = (function(){
	var 
	 getSlot 	= /{(\d+)}/g
	,replace 	= String.prototype.replace
	,replaceEl	= function(m, i){
		return this[i]; // this为arguments
	};

	return function(){
		replaceEl.scope = arguments;// 委托作用域
		return replace.call(this, getSlot, replaceEl.delegate());
	}
})();

String.trim = function(str){
	return str.replace(String.trimReg, '');
};
String.trimReg = /^[\s\t\r\n]+|[\s\t\r\n]+$/g;

/**
 * 日期格式化。
 * 详见我博客文章：http://blog.csdn.net/zhangxin09/archive/2011/01/01/6111294.aspx
 * e.g: new Date().format("yyyy-MM-dd hh:mm:ss")
 * @param 	{String} format
 * @return	{String}
 */
Date.prototype.format = function(format){
    var 
	 $1
    ,o = {
         "M+": this.getMonth() + 1 		// 月份，从0开始算
        ,"d+": this.getDate()    		// 日期
        ,"h+": this.getHours()   		// 小时
        ,"m+": this.getMinutes() 		// 分钟
        ,"s+": this.getSeconds() 		// 秒钟
       									// 季度quarter
        ,"q+": Math.floor((this.getMonth() + 3) / 3)  
        ,"S" : this.getMilliseconds() 	// 千秒
    }
    ,key
    ,value;

    if (/(y+)/.test(format)) {
    	 $1		= RegExp.$1
    	,format = format.replace($1, String(this.getFullYear()).substr(4 - $1));
    }
    // 如果没有指定该参数，则子字符串将延续到 stringvar 的最后。
    for (key in o){
	    if(new RegExp("(" + key + ")").test(format)){
    		 $1		= RegExp.$1
	    	,value	= String(o[key])
	    	,value	= $1.length == 1 ? value : ("00" + value).substr(value.length)
    		,format = format.replace($1, value);
	    }
    } 
    return format;	
}

//// 日期功能 by  Liu Shuan
//Core.lib.date = function() {
//	// 格式化日期
//	this.formatDate = function(date, style) {
//		style = style || "yyyy-MM-ddThh:mm:ss";
//		return style.replace(/y+|M+|d+|h+|m+|s+|w+|q+|S/g, function($0) {
//			var temp = 0;
//			switch ($0.charAt(0)) {
//				case "y" :
//					return String(date.getFullYear()).substr(4 - $0.length);
//				case "w" :
//					return "日一二三四五六".charAt(date.getDay());
//				case "q" :
//					return Math.floor((date.getMonth() + 3) / 3);
//				case "S" :
//					return date.getMilliseconds();
//
//				case "M" :
//					temp = date.getMonth() + 1;
//					break;
//				case "d" :
//					temp = date.getDate();
//					break;
//				case "h" :
//					temp = date.getHours();
//					break;
//				case "m" :
//					temp = date.getMinutes();
//					break;
//				case "s" :
//					temp = date.getSeconds();
//					break;
//			}
//
//			return (temp < 10 && $0.length == 2) ? "0" + temp : temp;
//		});
//	}
//
//	var cache1 = {};
//	var cache2 = {};
//
//	// 解析出日期
//	this.parseDate = function(text, style) {
//
//		style = style || "y-M-d";
//
//		// 匹配的模板 || 兼缓存
//		var pattern = cache1[style] || (cache1[style] = RegExp().compile(style.replace(/([Mdyhms])/g, "(\\d+)")));
//
//		// 匹配的顺序 || 兼缓存
//		var order = cache2[style]|| (cache2[style] = ("^" + style.replace(/[^Mdyhms]/g, '')).split(''));
//
//		// 匹配的项目 || 不可缓存
//		var match = pattern.exec(text);
//
//		// 匹配的结果 （顺序对应项目）
//		var result = {}
//		for (var i = 1; i < order.length; i++) {
//			result[order[i]] = match[i];
//		}
//
//		// 按照构造参数进行构造
//		var args = "M/d/y h:m:s".replace(/[Mdyhms]/g, function($0) {return result[$0] || 0;});
//
//		return new Date(args);
//	}
//}

/**
 * 继承。
 * @param {this} 		superClass
 * @param {Object}		subInstance
 * @return {Any}
 */
Function.prototype.extend = function(subInstance){
	var
	 superClass		= this
	,supClassPro	= superClass.prototype 
	,subClassPro	= subInstance.constructor.prototype
	,result;
	
	// call super
	result = superClass.apply(
		 subClassPro
		,Array.prototype.slice.call(arguments, 1)
	);
	
	// 遍历父对象的prototype成员拷贝到当前对象的prototype。
	for(var i in supClassPro){
		subClassPro[i] = supClassPro[i];
	}
	
	return result;
}

/**
 * 
 * forece Args！ so there's no args, it server as Args!
 * 预设函数的作用域。考查下面两个方法：
	Function.prototype.delegateScope = function (scope){
		var self = this;
	    return function(){
	        return self.apply(scope, arguments);
	    }
	}
	
	Function.prototype.delegateArgs = function(){
	    var 
		     self 	 = this
		    ,args	 = arguments;
		    
	    return function(){
	        return self.apply(this, args);
	    };
	}
 * @return {Function}
 */
Function.prototype.delegate = function(){
    var 
     self 	 = this
    ,scope	 = this.scope 
    ,args	 = arguments
    ,aLength = arguments.length;

    return function(){
        var 
        	 bLength = arguments.length
        	,Length  = (aLength > bLength) ? aLength : bLength;
        
        for(var i = 0; i < Length; i++){
	    	if(arguments[i]){
	    		args[i] = arguments[i];
	    	}
        }   
        // 在 MS jscript下面，rguments作为数字来使用还是有问题，就是length不能自动更新。修正如下:
        args.length = Length;
        return self.apply(scope || this, args);
    };
}

/**
 * 修改function的参数。
 * @param  {Number}		argIndex	指定哪一个参数？
 * @param  {Function}	filterFn 	修改的函数
 * @param  {Boolean}	isArray		还要指定第几个的参数？
 * @return {Function}
 */
Function.prototype.delegateArg = function(argIndex, filterFn, isArray){
    var 
	 self	 = this
	,toArray = Array.prototype.slice;
    	
    return function(){
        var args = toArray.call(arguments, 0);	// 变为真正数组。
        
        if(isArray){
        	args[argIndex] = filterFn.apply(this, arguments);
        }else{
	        args[argIndex] = filterFn.call (this, arguments[argIndex]);
        }
        
        return self.apply(this, args);
    };
}

/**
 * 设置一个后置函数。
 * @param  {Function} composeFn
 * @return {Function}
 */
Function.prototype.after = function(composeFn){
    var self = this;

    return function(){
        var result	= self.apply(this, arguments);
        
        return result && (typeof result.pop != 'undefined') && (typeof result.pop != 'unknown')
    		 ? composeFn.apply(this, result)
    		 : composeFn.call (this, result);
    };
}

/**
 * 设置一个前置函数。
 * @param  {Function} sequenceFn
 * @return {Function}
 */
Function.prototype.before = function(sequenceFn){
    var self = this;

    return function(){
        var result = sequenceFn.apply(this, arguments);

        return result && (typeof result.pop != 'undefined') && (typeof result.pop != 'unknown')
    		 ? self.apply(this, result)
    		 : self.call (this, result);
    };
}

/**
 * @param  {Array} 		arr
 * @return {Function}
 */
Function.prototype.map = function(arr){
	var 
	 self		= this
	,fixArgs	= Array.prototype.slice;
		
	return function(){
		var 
			 args = fixArgs.call(arguments, 1)
		 	,result;
		 	
		for(var i = 0, j = arr.length, result = new Array(j); i < j; i++){
			result[i] = self.apply(this, args.concat(arr[i]));
		}
		return result;
	}
}

/**
 * fn与参数的关系。
 * @param {Array}	arr
 * @param {Object} 	init
 * @param {Any}
 */
Function.prototype.reduce = function(arr, init){
	for(var i = 0, j = arr.length; i < j; i++){
		init = this.call(init || this, arr[i]);
	}
	return init;
}

/* 
 * *----------------*
 *  Require
 * *----------------*
 */
$$.require = function(_package){
	if(!_package){
		throw "必须输入args对象！";
	}else if(arguments.length > 1){
    	arguments.callee.reduce(arguments);
    }else if(_package._tokenString || typeof _package == "string" ){
        var filePath = _package._tokenString	// get token by Static member
        			|| _package;				// 传入字符串就是资源的路径。
        
        filePath += ".js";
        arguments.callee.eval_JS_File(filePath);
    }else if(
		(typeof _package == "function")
		||
		(_package.constructor && typeof _package.constructor == "function"  && !_package._tokenString)
		||
		(_package._loaded == true)// _package.prototype.loaded is token to know if loaded
		||
		(_package.prototype && _package.prototype._loaded == true)
	){
    	return _package; // 已经加载了，不重复加载
    }else{
        debugger;
    }
    return true; // done.
}
// prototype
$$.require.eval_JS_File = function(file){

}
;(function(){
    function eval_JS_File_MS_ASP_JScript(filePath){
    	
	// for MS ASP Boost file
	    Response.Charset		= "utf-8";
	    Session.CodePage		= 65001;
	    Session.Timeout			= 200;
	    Server.ScriptTimeout	= 100;
    
        if(arguments.length > 1){
            argsList(arguments, arguments.callee);
        }else{
            with (new ActiveXObject("Adodb.Stream")){
                type = 2;
                mode = 3;
                charset = "utf-8";
                open();
                if(typeof($$.console) != 'undefined' && $$.console.log){
                	$$.console.log(filePath);
                	$$.console.log(Server.Mappath(filePath));
                }
                loadFromFile(Server.Mappath(filePath));
                var source = readText();
                eval(source);
                close();
            }
        }
    }
    function eval_JS_File_Browser(src){
        if(arguments.length > 1){
            argsList(arguments, arguments.callee);
        }else{
        	var scriptTag = '<scr' + 'ipt src="{0}"></sc' + 'ript>';
        	
        	if($$.env.isHTA){ // HTA环境下不支持“/”路径，只支持相对路径。
        		scriptTag = '<scr' + 'ipt src="http://localhost/{0}"></sc' + 'ript>';
        	}
            document.write(scriptTag.format(src));
        }
    }
    // @todo
    function eval_JS_File_NodeJS(file){
    }
    
    if(typeof Server != 'undefined'){
	    $$.require.eval_JS_File = eval_JS_File_MS_ASP_JScript;
    }else if(document){
    	$$.require.eval_JS_File = eval_JS_File_Browser;
    }
})();

/* *----------------*
 *  Require
 * *----------------*
 */
 
/* 
 * *----------------*
 *  Debug
 * *----------------*
 */
$$.l = function(a){
	if(typeof $$.console != 'undefined' && $$.console.log){
		$$.console.log(a);
		return;
	}
    if(typeof(Response) != 'undefined' ){
        Response.write(a);
    }else{
        if(typeof $$.console != 'undefined' && $$console.log){
            $$.console.log(a);
        }else{
        	$$.l.count++;
        	if($$.l.count > $$.l.showLimit ){
        		return;
        	}else{
	            if($$.l.count == $$.l.showLimit ){
		            alert('Too much errors! Not Boring?');
		            return;
	            }
	            alert(a);
        	}
        }
    }
}
$$.l.count = 0;
$$.l.showLimit = 5;
l=$$.l;
/* 
 * *----------------*
 *  Debug
 * *----------------*
 */
 
 